ChatGPTだけでESLintのプラグインを作ってみた powered by OpenAI
2024/07/31(水)18:00-19:00
すみません。生成AIネタが思いつきませんでした。
全然生成AIを使いこなしていないマンです。
ということで、ファイル内にuseEffectの記述が3回出てきたら、エラーを出すようなESLintのプラグインでも作ってみようか。。 成果物
使用したもの
まずはデモを見ましょう!
https://scrapbox.io/files/66a9f45e2ffb09001d526a39.mov
最初の質問(仕様)
https://gyazo.com/3c7b55991918a5e6a73bbd6b8acd0b03
最初は、useStateが3つ以上あるときに警告出すプラグインを作ってみようと思った。
なので同じような内容を聴いてみた。
https://gyazo.com/6b5989f3b68197bfbfd54cf9838b2f5c
返ってきた内容
ルールの実装
code:javascript
module.exports = {
meta: {
type: "problem", // "problem", "suggestion", or "layout"
docs: {
description: "disallow more than 2 useEffect hooks in a file",
category: "Best Practices",
recommended: false,
},
schema: [], // no options
messages: {
tooManyUseEffect: "File has more than 2 useEffect hooks",
},
},
create(context) {
let useEffectCount = 0;
return {
ImportDeclaration(node) {
if (node.source.value === "react") {
node.specifiers.forEach(specifier => {
if (specifier.imported && specifier.imported.name === "useEffect") {
useEffectCount++;
}
});
}
},
CallExpression(node) {
if (node.callee.name === "useEffect") {
useEffectCount++;
if (useEffectCount > 2) {
context.report({
node,
messageId: "tooManyUseEffect",
});
}
}
},
};
},
};
プラグインのエントリーポイント (index.js)にルールを追加
code:javascript
module.exports = {
rules: {
"no-multiple-useeffect": require("./lib/rules/no-multiple-useEffect"),
},
};
テストの追加
code:javascript
const { RuleTester } = require("eslint");
const rule = require("../../../lib/rules/no-multiple-useEffect");
const ruleTester = new RuleTester({
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
});
ruleTester.run("no-multiple-useEffect", rule, {
valid: [
{
code: `
import React, { useEffect } from 'react';
const Component = () => {
useEffect(() => {}, []);
useEffect(() => {}, []);
return <div></div>;
};
`,
},
],
invalid: [
{
code: `
import React, { useEffect } from 'react';
const Component = () => {
useEffect(() => {}, []);
useEffect(() => {}, []);
useEffect(() => {}, []);
return <div></div>;
};
`,
errors: messageId: "tooManyUseEffect" },
},
],
});
なんかそれっぽいぞ。。。!
ディレクトリ構成
code:Shell
eslint-plugin-no-multiple-useEffect/
├── lib/
│ └── rules/
│ └── no-multiple-useEffect.js
├── tests/
│ └── lib/
│ └── rules/
│ └── no-multiple-useEffect.js
├── index.js
└── package.json
とりあえず必要なパッケージをインストールする
code:sh
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
その後以下を実行してテストする
code:shell
npx eslint tests/lib/rules/no-multiple-useEffect.js
テストが通る。。。!
いけるじゃん!
Reactのプロジェクトから使う場合に、どうすればいいかChatGPTさんに聴く
npmパッケージに公開でも良かったがローカルでちゃんと読み込まれるか確認したかった。
https://gyazo.com/ce92c8f7e365785712d77606ff26c93a
それっぽいのが返ってきた
create-react-appをしてプロジェクト作成する
react-appが出来上がったらプロジェクトのルートに今回作ったESLintのパッケージをコピーして配置する
ディレクトリ構造こんな感じ
code:shell
myProject/
├── eslint-plugin-no-multiple-useEffect/
│ ├── lib/
│ │ └── rules/
│ │ └── no-multiple-useEffect.js
│ ├── tests/
│ │ └── lib/
│ │ └── rules/
│ │ └── no-multiple-useEffect.js
│ ├── index.js
│ └── package.json
└── react-app/
├── eslint-plugin-no-multiple-useEffect/
├── src/
│ └── TestComponent.tsx
├── .eslintrc.js
└── package.json
react-appに必要なパッケージを入れる
code:sh
cd react-app
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
cp -r ../eslint-plugin-no-multiple-useEffect ./eslint-plugin-no-multiple-useEffect
.eslintrc.jsをreact-app/のルールに配置する
TestComponent.tsxにサンプルコードを書いてみる
code:typescript
import React, { useEffect } from 'react';
const TestComponent = () => {
useEffect(() => {
console.log('First useEffect');
}, []);
useEffect(() => {
console.log('Second useEffect');
}, []);
useEffect(() => {
console.log('Third useEffect');
}, []);
return <div>Test Component</div>;
};
export default TestComponent;
ここまできたら
code:shell
npx eslint tests/lib/rules/no-multiple-useEffect.js
を実行する
エラーになる!!!
原因(色々あるけど)主に2つ
Reactプロジェクト側とプラグイン側のESLintのバージョンの不一致
eslint-plugin-no-multiple-useeffectがローカルだと読み込めない
Reactプロジェクト側とプラグイン側のESLintのバージョンの不一致 単純にReact側のESLintのバージョンがv9となっていてプラグイン側のESLintのバージョン(v8)と噛み合っていない
あと依存解決もできていなかった
プラグイン側を後で自分で修正するとして今回はReact側の方をv8にダウングレードさせる対応をとる
と同時に--legacy-peer-depsを実行する
eslint-plugin-no-multiple-useEffectがローカルだと読み込めない
ChatGPTに聴いてみると以下を実行してくれと言われた
npm link
パブリックなpackageとして公開しなくても、別のプロジェクトから公開されたpackageと同じように参照することが可能になる。
しかしこれでも今回は解決しなかった。。。
代替手段
package.jsonに以下を記述
code:json
{
"dependencies": {
"eslint-plugin-no-multiple-useEffect": "file:../eslint-plugin-no-multiple-useEffect"
}
}
直接ファイルを指定する
その後npm install
code:sh
npm install ../eslint-plugin-no-multiple-useEffect/eslint-plugin-no-multiple-useEffect-1.0.0.tgz --legacy-peer-deps
その後
code:sh
npx eslint tests/lib/rules/no-multiple-useEffect.js
動いた!!!!!!!!
ここまで1時間掛からずできた
エラーが出ても今回はChatGPTになんとか解決させようと質問をした
ChatGPTが理解してくれなかったこと
ESLintのバージョン不一致や依存関係
これは仕方ないかも→エラーがでた時点で分かってはいたけど、質問を変更しても、同じ手順を返してきたりして4ラリーぐらいした
使う側とライブラリ側でバージョンが違うのでダウングレードさせると良かったりします?という質問をしたら分かったような返しをしつつ全然解決しないコマンドを返してきた
学べたこと
普段packageの開発はしないので、こんなことできるんだという知見を得た
eslintプラグインを自作する手順がなんとなく分かった
今後やりたいこと
リファクタリングする
ESLint v9対応にする
今は3つ以上で決め打ちになっているので、制限できるuseEffectの数を選択できるようにする
ご清聴ありがとうございました!